/*******************************************************************************
 * Copyright (c) 2018, 2018 Grimm
 ******************************************************************************/
package com.alex.java8_03;

import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

import org.junit.Test;

import com.alex.java8_01.Employee;

/**
 * @Description
 *              <p>
 *              Lambda 表达式中的各种引用
 *              一.方法引用：若Lambda 体中的内容有方法已经实现了，我们可以使用“方法引用”
 *              可以理解为方法引用是 Lambda表达式的另外一种表现形式
 *              主要有三种语法格式：
 *              对象：：实例方法名
 *              类：：静态方法名
 *              类：：实例方法名
 *              注意：
 *              ① Lambda 体中调用方法的参数列表与返回值类型，要与函数式接口中抽象方法的函数列表和返回值类型保持一致！
 *              ② 若 Lambda 参数列表中的第一参数是实例方法的调用者，而第二个参数是实例方法的参数时，可以使用 ClassName::method
 *              二.构造器引用
 *              格式：ClassName::new
 *              注意：需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致！
 *              三.数组引用
 *              Type[]::new
 */
public class TestLambdaRef {

	// 方法引用 （对象：：实例方法名）
	@Test
	public void test1() {
		// 传统Lambda 表达式写法
		Consumer<Integer> con = (x) -> System.out.println("消费了 " + x + " 元");
		con.accept(100);

		// 方法引用写法
		PrintStream ps = System.out;// ps 是一个对象
		Consumer<Integer> con2 = ps::println;// 或者直接写 System.out::print
		con2.accept(200);

		// 再举一个例子
		Employee em = new Employee();
		Supplier<String> sup = () -> em.getName();
		String string = sup.get();
		System.out.println("此人名字叫做：   " + string);

		// 方法引用写法
		Supplier<Integer> sup2 = em::getAge;
		System.out.println("此人年龄为 ： " + sup2.get());
	}

	// 方法引用 （类：：静态方法名）
	@Test
	public void test2() {
		// 传统 Lambda 表达式写法
		Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
		int compare = com.compare(4, 5);
		System.out.println(compare);

		// 方法引用写法
		Comparator<Integer> com2 = Integer::compare;
		int compare2 = com2.compare(5, 3);
		System.out.println(compare2);
	}

	// 方法引用 （类：：实例方法名）
	@Test
	public void test3() {
		// 传统 Lambda 表达式写法
		BiPredicate<String, String> biPre = (x, y) -> x.equals(y);
		boolean test = biPre.test("acb", "aec");
		System.out.println(test);

		// 方法引用写法(第一个参数是实例方法的调用者，第二个参数是实例方法的参数)
		BiPredicate<String, String> biPre2 = String::equals;
		boolean test2 = biPre2.test("acb", "acb");
		System.out.println(test2);
	}

	// 构造器引用 （ClassName::new）
	@Test
	public void test4() {
		// 传统 Lambda 表达式写法
		Supplier<Employee> sup = () -> new Employee();
		Employee employee = sup.get();
		System.out.println(employee);

		// 构造器引用写法
		Supplier<Employee> sup2 = Employee::new;
		Employee employee2 = sup2.get();
		System.out.println(employee2);
	}

	// 数组引用 (Type[]::new)
	@Test
	public void test5() {
		// 传统 Lambda 表达式写法
		Function<Integer, String[]> sup = (num) -> new String[num];
		String[] arrays1 = sup.apply(10);
		System.out.println(arrays1.length);

		// 数组引用写法
		Function<Integer, String[]> sup2 = String[]::new;
		String[] arrays2 = sup2.apply(20);
		System.out.println(arrays2.length);
	}
}
